package com.plian.system.service.im.impl;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.plian.Tools.*;
import com.plian.Tools.pagedata.PageData;
import com.plian.system.common.status.CheckStatus;
import com.plian.system.common.status.CustomCode;
import com.plian.system.constant.baseinfo.ValueSetConstant;
import com.plian.system.constant.sys.FormStatusConstant;
import com.plian.system.constant.sys.FormTypeConstant;
import com.plian.system.constant.yth.YthConstant;
import com.plian.system.dao.sys.orgzation.OrgzationDao;
import com.plian.system.dto.im.BaseInvestmentExecutionDTO;
import com.plian.system.dto.im.BaseInvestmentExecutionNewDTO;
import com.plian.system.entity.im.*;
import com.plian.system.entity.sys.ApprovalMessage;
import com.plian.system.entity.sys.Region;
import com.plian.system.enumeratea.CheckName;
import com.plian.system.mapper.im.BaseInvestmentExecutionNewMapper;
import com.plian.system.mapper.im.BaseInvestmentPlanMapper;
import com.plian.system.mapper.im.MainProjectSituationMapper;
import com.plian.system.mapper.im.ProjectInfoMapper;
import com.plian.system.model.CommonCode;
import com.plian.system.model.R;
import com.plian.system.mybatis.base.BaseFlowService;
import com.plian.system.mybatis.base.BaseServiceImpl;
import com.plian.system.mybatis.search.SearchParamEntiy;
import com.plian.system.mybatis.search.TokenSearch;
import com.plian.system.mybatis.support.Condition;
import com.plian.system.mybatis.support.Query;
import com.plian.system.service.bt.baseinfo.BaseInfoService;
import com.plian.system.service.im.IBaseInvestmentExecutionNewService;
import com.plian.system.service.im.IEffectiveInvestmentService;
import com.plian.system.service.im.IFundProjectService;
import com.plian.system.service.sys.code.IFormCodeService;
import com.plian.system.service.sys.message.IApprovalMessageService;
import com.plian.system.service.sys.orgzation.IOrgService;
import com.plian.system.service.sys.orgzation.OrgzationService;
import com.plian.system.service.sys.region.IRegionService;
import com.plian.system.service.wf.FormWorkflowService;
import com.plian.system.vo.im.*;
import com.plian.system.vo.report.ChartsVO;
import com.plian.system.vo.report.LegendVO;
import com.plian.system.vo.report.SeriesVO;
import com.plian.system.vo.report.XAxisVO;
import com.plian.system.vo.yth.YthResult;
import com.plian.system.wrapper.im.BaseInvestmentExecutionNewWrapper;
import com.plian.system.wrapper.im.EffectiveInvestmentWrapper;
import com.plian.system.wrapper.im.FundProjectWrapper;
import com.plian.system.wrapper.im.ProjectInfoWrapper;
import lombok.AllArgsConstructor;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.plian.system.constant.sys.ApprovalMessageTypeConstant.INVESTMENT_EXECUTION;
import static com.plian.system.constant.sys.ApprovalMessageTypeConstant.KT_TYPE;
import static com.plian.system.constant.sys.FormStatusConstant.UNREVIEWED;

/**
 * 服务实现类
 *
 * @author
 * @since 2019-09-27
 */
@Service
@AllArgsConstructor
public class BaseInvestmentExecutionNewServiceImpl extends BaseServiceImpl<BaseInvestmentExecutionNewMapper, BaseInvestmentExecutionNew> implements IBaseInvestmentExecutionNewService, BaseFlowService {

    private FormWorkflowService formWorkflowService;

    private BaseInvestmentPlanMapper baseInvestmentPlanMapper;

    private MainProjectSituationMapper mainProjectSituationMapper;

    private IEffectiveInvestmentService effectiveInvestmentService;

    private IFundProjectService fundProjectService;

    private Environment environment;

    private IFormCodeService formCodeService;

    private BaseInfoService baseInfoService;

    private OrgzationDao orgzationDao;

    private BaseInvestmentExecutionNewWrapper baseInvestmentExecutionWrapper;

    private EffectiveInvestmentWrapper effectiveInvestmentWrapper;

    private FundProjectWrapper fundProjectWrapper;

    private IApprovalMessageService approvalMessageService;

    private IOrgService orgService;

    private ProjectInfoMapper projectInfoMapper;

    private ProjectInfoWrapper projectInfoWrapper;

    private OrgzationService orgzationService;

    private IRegionService regionService;
    /**
     * logger属性.
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(BaseInvestmentExecutionNewServiceImpl.class);

    @Override
    public boolean saveOrUpdate(BaseInvestmentExecutionNew baseInvestmentExecution) {

        if (!Optional.ofNullable(baseInvestmentExecution.getStatus()).isPresent()) {
            baseInvestmentExecution.setStatus(FormStatusConstant.UNREVIEWED);
        }
        if (!Optional.ofNullable(baseInvestmentExecution.getId()).isPresent()) {
            baseInvestmentExecution.setCode(formCodeService.getCode(FormTypeConstant.IM_BASE_INVESTMENT_EXECUTION_FORM));
            baseInvestmentExecution.setFormType(String.valueOf(FormTypeConstant.IM_BASE_INVESTMENT_EXECUTION_FORM));
        }
        return super.saveOrUpdate(baseInvestmentExecution);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public boolean deleteLogic(List<Long> ids) {
        for (Long id : ids) {
            BaseInvestmentExecutionNew baseInvestmentExecution = getById(id);
            if (baseInvestmentExecution == null) {
                return false;
            } else if (baseInvestmentExecution.getStatus() != null &&
                    (baseInvestmentExecution.getStatus() != FormStatusConstant.STASH && baseInvestmentExecution.getStatus() != FormStatusConstant.UNREVIEWED)) {
                return false;
            }
            formWorkflowService.deleteProcessInstance(String.valueOf(id));
        }

        boolean result = super.deleteLogic(ids);
        if (result) {
            effectiveInvestmentService.deleteByParentId(ids);
            fundProjectService.deleteByParentId(ids);
        }
        return result;
    }

    @Override
    public HashMap<String, Object> commit(String id) {
        handleStatus(Long.valueOf(id), FormStatusConstant.FLOW, null);

        //将需要提交的流程变量返回，用于工作流侧
        return new HashMap<String, Object>();
    }

    @Override
    public Boolean finish(String id) {
        return handleStatus(Long.valueOf(id), FormStatusConstant.FINISH, "审批通过");
    }

    @Override
    public Boolean reject(String id, int formState, String comment) {
        return handleStatus(Long.valueOf(id), formState, comment);
    }


    /**
     * 统一处理状态机事件方法
     *
     * @param id           主键
     * @param updateStatus 更新状态
     * @return boolean
     */
    private Boolean handleStatus(Long id, int updateStatus, String comment) {
        try {
            BaseInvestmentExecutionNew baseInvestmentExecution = getById(id);
            /**
             * 设置审批人和审批时间
             */
            if (updateStatus == FormStatusConstant.FINISH) {
                baseInvestmentExecution.setApprovedUser(TokenUtil.getTokenUserId());
                Date now = DateUtil.now();
                baseInvestmentExecution.setApprovedTime(now);
            }
            if (StringUtil.isNotBlank(baseInvestmentExecution.getDataSource()) &&
                    StringUtil.isNotBlank(baseInvestmentExecution.getDataSourceId())
                    && !YthConstant.DATA_NINGBO.equals(baseInvestmentExecution.getDataSource())) {
                if (updateStatus == FormStatusConstant.FINISH || updateStatus == FormStatusConstant.REJECT) {
                    ApprovalMessage approvalMessage = new ApprovalMessage();
                    approvalMessage.setDataSourceId(baseInvestmentExecution.getDataSourceId());
                    approvalMessage.setType(INVESTMENT_EXECUTION);
                    approvalMessage.setOpinion(comment);
                    approvalMessage.setIsApprove(updateStatus == FormStatusConstant.FINISH ? 2 : 1);
                    approvalMessage.setIsSend(1);
                    approvalMessage.setDataSourceType(KT_TYPE);
                    approvalMessage.setFilingCode(baseInvestmentExecution.getCode());
                    approvalMessageService.save(approvalMessage);
                }
            }
            baseInvestmentExecution.setStatus(updateStatus);
            updateById(baseInvestmentExecution);
            return true;
        } catch (Exception e) {
            log.error(ExceptionUtils.getFullStackTrace(e));
            return false;
        }
    }


    @Override
    public List<PageData> findByIds(List<String> formIds) {
        LambdaQueryWrapper<BaseInvestmentExecutionNew> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(BaseInvestmentExecutionNew::getId, Func.toLongList(StringUtils.join(formIds, StringPool.COMMA)));
        List<BaseInvestmentExecutionNew> baseInvestmentExecutions = list(queryWrapper);
        List<BaseInvestmentExecutionNewVO> baseInvestmentExecutionVOS = baseInvestmentExecutionWrapper.entityToVO(baseInvestmentExecutions);
        List<PageData> pageDataList = new ArrayList<>();
        try {
            if (CollectionUtil.isNotEmpty(baseInvestmentExecutionVOS)) {
                for (BaseInvestmentExecutionNewVO vo : baseInvestmentExecutionVOS) {
                    PageData pd = new PageData();
                    pd.put("id", vo.getId());
                    pd.put("UNITNAME", vo.getFilingUnitName());
                    pd.put("APPLICANTNAME", vo.getCreateUserName());
                    pd.put("applicantId", vo.getCreateUser());
                    pd.put("applyOrganizationId", vo.getFilingUnitId());
                    pd.put("formType", FormTypeConstant.IM_BASE_INVESTMENT_EXECUTION_FORM);
                    pd.put("orgName", vo.getFilingUnitName());
                    pageDataList.add(pd);
                }
            }

            return pageDataList;
        } catch (Exception e) {
            log.error(ExceptionUtils.getFullStackTrace(e));
        }
        return pageDataList;
    }

    @Override
    public List<Integer> getFormType() {
        return Collections.singletonList(FormTypeConstant.IM_BASE_INVESTMENT_EXECUTION_FORM);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public boolean submit(BaseInvestmentExecutionNew baseInvestmentExecution) {
        boolean result = saveOrUpdate(baseInvestmentExecution);
        if (result) {
            EffectiveInvestment effectiveInvestment = baseInvestmentExecution.getEffectiveInvestment();
            if (Optional.ofNullable(effectiveInvestment).isPresent()) {
                if (effectiveInvestment.getId() != null &&
                        Optional.ofNullable(effectiveInvestment.getIsDeleted()).isPresent() && effectiveInvestment.getIsDeleted().intValue() == 1) {
                    effectiveInvestmentService.removeById(effectiveInvestment.getId());
                } else {
                    effectiveInvestment.setBaseInvestmentExecutionId(baseInvestmentExecution.getId());
                    effectiveInvestmentService.submit(effectiveInvestment);
                }
            }

            List<FundProject> fundProjects = baseInvestmentExecution.getFundProjects();
            if (CollectionUtil.isNotEmpty(fundProjects)) {
                for (FundProject fundProject : fundProjects) {
                    if (fundProject.getId() != null &&
                            Optional.ofNullable(fundProject.getIsDeleted()).isPresent() && fundProject.getIsDeleted().intValue() == 1) {
                        fundProjectService.removeById(fundProject.getId());
                    } else {
                        fundProject.setBaseInvestmentExecutionId(baseInvestmentExecution.getId());
                        fundProjectService.submit(fundProject);
                    }
                }
            }
        }

        return result;
    }

    @Override
    public R<BaseInvestmentExecutionNewVO> getDetailObj(BaseInvestmentExecutionNewVO baseInvestmentExecutionVO) {
        if (!Optional.ofNullable(baseInvestmentExecutionVO).isPresent()) {
            return new R(CommonCode.FAIL);
        }

        R<BaseInvestmentExecutionNewVO> objResult = new R<>(CommonCode.SUCCESS);
        EffectiveInvestmentVO effectiveInvestmentVO = effectiveInvestmentWrapper.entityToVO(
                effectiveInvestmentService.getOne(new LambdaQueryWrapper<EffectiveInvestment>()
                        .eq(EffectiveInvestment::getBaseInvestmentExecutionId, baseInvestmentExecutionVO.getId())));
        baseInvestmentExecutionVO.setEffectiveInvestmentVO(effectiveInvestmentService.getDetailPd(effectiveInvestmentVO));
        List<FundProjectVO> fundProjectVOS = fundProjectWrapper.entityToVO(fundProjectService.list(new LambdaQueryWrapper<FundProject>()
                .eq(FundProject::getBaseInvestmentExecutionId, baseInvestmentExecutionVO.getId())));
        baseInvestmentExecutionVO.setFundProjectVOS(fundProjectService.getDetailPd(fundProjectVOS));
        objResult.setPageData(baseInvestmentExecutionVO);
        return objResult;
    }


    @Override
    public String checkMonth(BaseInvestmentExecutionNew baseInvestmentExecution) {
        LambdaQueryWrapper<BaseInvestmentExecutionNew> queryWrapper = new LambdaQueryWrapper<>();
        if (!Optional.ofNullable(baseInvestmentExecution.getFilingMonth()).isPresent()) {
            return "填报时间为空";
        }
        if (!Optional.ofNullable(baseInvestmentExecution.getFilingUnitId()).isPresent()) {
            return "填报单位为空";
        }
        queryWrapper.eq(BaseInvestmentExecutionNew::getFilingUnitId, baseInvestmentExecution.getFilingUnitId());
        queryWrapper.eq(BaseInvestmentExecutionNew::getFilingMonth, baseInvestmentExecution.getFilingMonth());
        BaseInvestmentExecutionNew one = this.getOne(queryWrapper);
        if (!Optional.ofNullable(one).isPresent()) {
            return null;
        }
        if (one.getId().equals(baseInvestmentExecution.getId())) {
            return null;
        }
        return "该月份已填报";
    }

    @Override
    public String export(Long baseInvestmentExecutionId) {

        String key = baseInvestmentExecutionId + StringPool.DASH + UUID.randomUUID().toString().replace(StringPool.DASH, "");
        String fileName = key + ".xlsx";
        String exportPath = environment.getProperty("excel.path");
        LOGGER.info("BaseInvestmentExecutionNewServiceImpl baseInvestmentExecutionId--exportPath--->" + exportPath);
        /**
         * 导出路径不存在则创建
         */
        File file = new File(exportPath);
        if (!file.exists()) {
            file.mkdirs();
        }
        InputStream inputStream = this.getClass().getResourceAsStream("/exceldemo/investmentExecution.xlsx");
        ExcelWriter excelWriter = EasyExcel.write(exportPath + fileName).withTemplate(inputStream).build();

        // 这里注意 入参用了forceNewRow 代表在写入list的时候不管list下面有没有空行 都会创建一行，然后下面的数据往后移动。默认 是false，会直接使用下一行，如果没有则创建。
        // forceNewRow 如果设置了true,有个缺点 就是他会把所有的数据都放到内存了，所以慎用
        // 简单的说 如果你的模板有list,且list不是最后一行，下面还有数据需要填充 就必须设置 forceNewRow=true 但是这个就会把所有数据放到内存 会很耗内存

        FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();

        // 表一
        WriteSheet effectiveInvestmentWriteSheet = EasyExcel.writerSheet(0).build();
        EffectiveInvestment effectiveInvestment = effectiveInvestmentService.getOne(new LambdaQueryWrapper<EffectiveInvestment>()
                .eq(EffectiveInvestment::getBaseInvestmentExecutionId, baseInvestmentExecutionId));
        if (null == effectiveInvestment) {
            effectiveInvestment = new EffectiveInvestment();
        }
        effectiveInvestmentService.write(effectiveInvestment, excelWriter, effectiveInvestmentWriteSheet, fillConfig);

//		// 表二
//		WriteSheet fundProjectWriteSheet = EasyExcel.writerSheet(1).build();
//		List<FundProject> fundProjects = fundProjectService.list(new QueryWrapper<FundProject>().eq("base_investment_execution_id", baseInvestmentExecutionId));
//		Map<String, String> projectMap =baseInfoService.getChildMap(ValueSetConstant.FUND_CATEGORY);
//		for (FundProject fundProject : fundProjects) {
//			fundProject.setFundCategory(projectMap.get(fundProject.getFundCategory()));
//		}
//		fundProjectService.write(fundProjects, excelWriter, fundProjectWriteSheet, fillConfig);
        BaseInvestmentExecutionNewVO baseInvestmentExecutionVO = baseInvestmentExecutionWrapper.entityToVO(getById(baseInvestmentExecutionId));

        // 其他参数可以使用Map封装
        Map<String, Object> otherMap = new HashMap<>(16);
        otherMap.put("filingUnitName", "");
        otherMap.put("filingMonth", "");

        excelWriter.fill(otherMap, effectiveInvestmentWriteSheet);
        //excelWriter.fill(otherMap, fundProjectWriteSheet);
        excelWriter.finish();
        return key;
    }

    @Override
    public void download(String key, HttpServletResponse response, OutputStream os) {
        Long baseInvestmentPlanId = Long.valueOf(key.split(StringPool.DASH)[0]);
        BaseInvestmentExecutionNewVO baseInvestmentDebtVO = baseInvestmentExecutionWrapper.entityToVO(getById(baseInvestmentPlanId));
        String excelName = "项目投资计划";
        String excelPath = environment.getProperty("excel.path") + "/" + key + ".xlsx";

        try {
            os = response.getOutputStream();//取得输出流
            response.reset();//清空输出流
            //下面是对中文文件名的处理
            response.setCharacterEncoding("UTF-8");//设置相应内容的编码格式

            InputStream inputStream = new FileInputStream(excelPath);
            excelName = java.net.URLEncoder.encode(excelName, "UTF-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + new String(excelName.getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8) + ".xlsx");

            response.setContentType("application/msexcel");//定义输出类型
            int len;
            byte[] b = new byte[2048];
            while ((len = inputStream.read(b)) != -1) {
                os.write(b, 0, len);
            }
            response.setHeader("Content-Length", String.valueOf(inputStream.available()));

            inputStream.close();
            os.close();
        } catch (Exception e) {
            log.error(ExceptionUtils.getFullStackTrace(e));
        } finally {
            /**
             * 删除文件
             */
            File file = new File(excelPath);
            if (file.exists() && file.isFile()) {
                file.delete();
            }
        }
    }

    @Override
    public void goBackToStash(String formId) {
        handleStatus(Long.valueOf(formId), UNREVIEWED, null);
    }

    @Override
    public R<BaseInvestmentExecutionNewVO> getLastMonthObj(BaseInvestmentExecutionNew baseInvestmentExecution) {
        String filingMonth = baseInvestmentExecution.getFilingMonth();
        Calendar c = Calendar.getInstance();
        c.setTime(DateUtil.parse(filingMonth, DateUtil.PATTERN_MONTH));
        c.add(Calendar.MONTH, -1);
        String lastMonth = DateUtil.format(c.getTime(), DateUtil.PATTERN_MONTH);
        BaseInvestmentExecutionNew last = getOne(new LambdaQueryWrapper<BaseInvestmentExecutionNew>()
                .eq(BaseInvestmentExecutionNew::getFilingUnitId, baseInvestmentExecution.getFilingUnitId())
                .eq(BaseInvestmentExecutionNew::getFilingMonth, lastMonth));
        BaseInvestmentExecutionNewVO baseInvestmentExecutionVO = new BaseInvestmentExecutionNewVO();
        if (Optional.ofNullable(last).isPresent()) {
            EffectiveInvestment effectiveInvestment = effectiveInvestmentService.getOne(
                    new LambdaQueryWrapper<EffectiveInvestment>().eq(EffectiveInvestment::getBaseInvestmentExecutionId, last.getId()));
            baseInvestmentExecutionVO.setEffectiveInvestmentVO(effectiveInvestmentService.getLastMainInfos(effectiveInvestment.getId()));

            List<FundProjectVO> fundProjectVOS = fundProjectWrapper.entityToVO(fundProjectService.list(new LambdaQueryWrapper<FundProject>()
                    .eq(FundProject::getBaseInvestmentExecutionId, last.getId())));
            baseInvestmentExecutionVO.setFundProjectVOS(fundProjectService.getLastMonthInfos(fundProjectVOS));
        } else {
            return new R(CustomCode.builder().message("上月无数据！").code(1999).success(false).build());
        }

        R objResult = new R(CommonCode.SUCCESS);
        objResult.setPageData(baseInvestmentExecutionVO);
        return objResult;
    }

    @Override
    public ChartsVO statisticsCompanyProportion(BaseInvestmentExecutionNewDTO baseInvestmentExecutionDTO) {
        try {
            String orgId = baseInvestmentExecutionDTO.getOrgId();
            if (StringUtil.isNotBlank(orgId)) {
                PageData org = orgzationDao.findbyid(orgId);
                if (org != null && !"0".equals(org.getString("parentId"))) {
                    List<String> fillingUnitIds = new ArrayList<>();
                    fillingUnitIds.add(orgId);
                    baseInvestmentExecutionDTO.setFillingUnitIds(fillingUnitIds);
                }
            }
        } catch (Exception e) {
            LOGGER.error(String.valueOf(e));
        }
        BaseInvestmentExecutionDTO dto = new BaseInvestmentExecutionDTO();
        BeanUtils.copyProperties(baseInvestmentExecutionDTO, dto);
        List<InvestmentMonthSummaryVO> results = effectiveInvestmentService.summary(dto);

        if (CollectionUtil.isEmpty(results)) {
            return null;
        }


        List<String> data = new ArrayList<>();
        data.add("完成率");
        LegendVO legendVO = LegendVO.builder().data(data).build();

        List<XAxisVO> xAxisVOS = new ArrayList<>();
        List<String> xList = new ArrayList<>();
        List<Object> companyProportionList = new ArrayList<>();
//		List<Object> planInvestmentTotalList = new ArrayList<>();
//		List<Object> allCompleteInvestmentList = new ArrayList<>();
        List<String> ids = new ArrayList<>();

        BigDecimal endPlanInvestmentTotal = new BigDecimal(0);
        BigDecimal endAllCompleteInvestmentList = new BigDecimal(0);
        for (int i = 0; i < results.size() - 1; i++) {
            InvestmentMonthSummaryVO result = results.get(i);
            if (StringUtil.isNotBlank(CheckName.getAbbreviationName(result.getUnitCheck()))) {
                xList.add(CheckName.getAbbreviationName(result.getUnitCheck()));
            } else {
                xList.add(result.getUnitCheck());
            }
//			planInvestmentTotalList.add(result.getPlanInvestmentTotal() != null ? result.getPlanInvestmentTotal() : 0);
//			allCompleteInvestmentList.add(result.getAllCompleteInvestment() != null ? result.getAllCompleteInvestment() : 0);
            companyProportionList.add(result.getCompleteProportion() != null ? result.getCompleteProportion() : 0 + StringPool.PERCENT);
            ids.add(result.getFilingUnitId());

            endPlanInvestmentTotal = BigDecimalUtil.add(endPlanInvestmentTotal, result.getPlanInvestmentTotal());
            endAllCompleteInvestmentList = BigDecimalUtil.add(endAllCompleteInvestmentList, result.getAllCompleteInvestment());
        }

        BigDecimal endCompanyProportion = BigDecimalUtil.divide(endAllCompleteInvestmentList, endPlanInvestmentTotal, 2, BigDecimal.ROUND_HALF_UP, 100);
        List<SeriesVO> seriesVOS = new ArrayList<>();
//		seriesVOS.add(SeriesVO.builder().name("计划投资额").type("bar").data(planInvestmentTotalList).build());
//		seriesVOS.add(SeriesVO.builder().name("完成投资额").type("bar").data(allCompleteInvestmentList).build());
        seriesVOS.add(SeriesVO.builder().name("完成率").type("bar").data(companyProportionList).build());
        xAxisVOS.add(XAxisVO.builder().data(xList).build());

        List<String> total = new ArrayList<>();
        total.add("总计划投资额: " + BigDecimalUtil.divide(endPlanInvestmentTotal, new BigDecimal(10000), 2, BigDecimal.ROUND_HALF_UP) + "亿元");
        total.add("累计实际投资额: " + BigDecimalUtil.divide(endAllCompleteInvestmentList, new BigDecimal(10000), 2, BigDecimal.ROUND_HALF_UP) + "亿元");
        total.add("完成率: " + endCompanyProportion + StringPool.PERCENT);
        ChartsVO chartsVO = ChartsVO.builder().legend(legendVO).ids(ids)
                .xAxis(xAxisVOS).series(seriesVOS).total(total).build();
        return chartsVO;
    }

    @Override
    public ChartsVO statisticsCompany(BaseInvestmentExecutionNewDTO baseInvestmentExecutionDTO) {
        /**
         * 填报年度为空时默认为当前年度
         */
        String filingYear = baseInvestmentExecutionDTO.getFilingYear();
        if (StringUtil.isBlank(filingYear)) {
            filingYear = DateUtil.format(DateUtil.now(), DateUtil.PATTERN_YEAR);
        }


        List<BaseInvestmentExecutionNew> results = baseMapper.queryByYear(baseInvestmentExecutionDTO.getFilingUnitId(), filingYear);
        if (CollectionUtil.isEmpty(results)) {
            return null;
        }

        InvestmentUnitSummaryVO planSummary = baseInvestmentPlanMapper.summaryPlanInvestment(filingYear, baseInvestmentExecutionDTO.getFilingUnitId());

        List<String> data = new ArrayList<>();
        data.add("股权投资");
        data.add("固定资产投资");
        data.add("重点项目");
        data.add("完成率");
        LegendVO legendVO = LegendVO.builder().data(data).build();

        List<XAxisVO> xAxisVOS = new ArrayList<>();
        List<String> xList = new ArrayList<>();

        List<Object> fixedList = new ArrayList<>();
        List<Object> stakeList = new ArrayList<>();
        List<Object> mainList = new ArrayList<>();
        List<Object> companyProportionList = new ArrayList<>();
        List<String> ids = new ArrayList<>();
        for (BaseInvestmentExecutionNew baseInvestmentExecution : results) {
            String month = Integer.valueOf(baseInvestmentExecution.getFilingMonth().split(StringPool.DASH)[1]) + "月";
            xList.add(month);
            BigDecimal fixedInvestment = new BigDecimal(0);
            BigDecimal stakeInvestment = new BigDecimal(0);
            BigDecimal mainInvestment = new BigDecimal(0);
            EffectiveInvestment effectiveInvestment = baseInvestmentExecution.getEffectiveInvestment();
            if (Optional.ofNullable(effectiveInvestment).isPresent()) {
                fixedInvestment = BigDecimalUtil.add(fixedInvestment, effectiveInvestment.getAllCompleteFixedInvestment());
                stakeInvestment = BigDecimalUtil.add(stakeInvestment, effectiveInvestment.getAllCompleteEquityInvestment());
                if (CollectionUtil.isNotEmpty(baseInvestmentExecution.getEffectiveInvestment().getMainProjectSituations())) {
                    for (MainProjectSituation mainProjectSituation :
                            baseInvestmentExecution.getEffectiveInvestment().getMainProjectSituations()) {
                        mainInvestment = BigDecimalUtil.add(mainInvestment, mainProjectSituation.getLastCompleteInvestment());
                        mainInvestment = BigDecimalUtil.add(mainInvestment, mainProjectSituation.getCompleteInvestment());
                    }
                }
            }

            if (baseInvestmentExecutionDTO.getUnitType() != null && baseInvestmentExecutionDTO.getUnitType() == 2) {
                fixedList.add(fixedInvestment != null ? BigDecimalUtil.divide(fixedInvestment, new BigDecimal(10000), 2, BigDecimal.ROUND_HALF_UP) : 0);
                stakeList.add(stakeInvestment != null ? BigDecimalUtil.divide(stakeInvestment, new BigDecimal(10000), 2, BigDecimal.ROUND_HALF_UP) : 0);
                mainList.add(mainInvestment != null ? BigDecimalUtil.divide(mainInvestment, new BigDecimal(10000), 2, BigDecimal.ROUND_HALF_UP) : 0);
            } else {
                fixedList.add(fixedInvestment != null ? fixedInvestment : 0);
                stakeList.add(stakeInvestment != null ? stakeInvestment : 0);
                mainList.add(mainInvestment != null ? mainInvestment : 0);
            }

            if (Optional.ofNullable(planSummary).isPresent()) {
                companyProportionList.add(BigDecimalUtil.divide(BigDecimalUtil.add(fixedInvestment, stakeInvestment),
                        planSummary.getInvestment(), 2, BigDecimal.ROUND_HALF_UP, 100));
            }
            ids.add(String.valueOf(baseInvestmentExecution.getId()));

        }

        List<SeriesVO> seriesVOS = new ArrayList<>();
        seriesVOS.add(SeriesVO.builder().name("股权投资").type("bar").data(fixedList).build());
        seriesVOS.add(SeriesVO.builder().name("固定资产投资").type("bar").data(stakeList).build());
        seriesVOS.add(SeriesVO.builder().name("重点项目").type("bar").data(mainList).build());
        seriesVOS.add(SeriesVO.builder().name("完成率").yAxisIndex(1).type("line").data(companyProportionList).build());

        xAxisVOS.add(XAxisVO.builder().data(xList).build());
        ChartsVO chartsVO = ChartsVO.builder().legend(legendVO).ids(ids)
                .xAxis(xAxisVOS).series(seriesVOS).build();
        return chartsVO;
    }

    @Override
    public ChartsVO statisticsProjectNature(BaseInvestmentExecutionNewDTO baseInvestmentExecutionDTO) {
        /**
         * 填报年月为空时默认为当前月份
         */
        String filingMonth = baseInvestmentExecutionDTO.getFilingMonth();
        if (StringUtil.isBlank(filingMonth)) {
            filingMonth = DateUtil.format(DateUtil.now(), DateUtil.PATTERN_MONTH);
        }

        List<MainProjectSituation> mainProjectSituations = mainProjectSituationMapper.queryByMonth(filingMonth, filingMonth.split(StringPool.DASH)[0]);
        if (CollectionUtil.isEmpty(mainProjectSituations)) {
            return null;
        }

        List<String> data = new ArrayList<>();
        data.add("完成率");
        LegendVO legendVO = LegendVO.builder().data(data).build();

        List<XAxisVO> xAxisVOS = new ArrayList<>();
        List<String> xList = new ArrayList<>();
        List<Object> companyProportionList = new ArrayList<>();
        List<String> ids = new ArrayList<>();

        Map<String, List<MainProjectSituation>> resultMap = mainProjectSituations.stream()
                .collect(Collectors.groupingBy(MainProjectSituation::getProjectNatureId));
        Map<String, String> projectMap = baseInfoService.getChildMap(ValueSetConstant.PROJECT_NATURE);
        List<String> keys = projectMap.keySet().stream().filter(key -> !Stream.of("070001", "070002", "070003", "070004", "070005", "070006")
                .collect(Collectors.toList()).contains(key)).collect(Collectors.toList());
        Set<String> projectNatureIdSet = new TreeSet<>(Comparator.naturalOrder());
        projectNatureIdSet.addAll(keys);

        List<Long> userProjectIds = new ArrayList<>();
        projectNatureIdSet.forEach(projectNatureId -> {
            ids.add(projectNatureId);
            xList.add(projectMap.get(projectNatureId));
            boolean flag = true;
            if (resultMap.containsKey(projectNatureId)) {
                BigDecimal planInvestment = new BigDecimal(0);
                BigDecimal completeInvestment = new BigDecimal(0);
                for (MainProjectSituation mainProjectSituation : resultMap.get(projectNatureId)) {
                    if (!userProjectIds.contains(mainProjectSituation.getProjectId())) {
                        planInvestment = BigDecimalUtil.add(planInvestment, mainProjectSituation.getPlanTotalInvestment());
                        userProjectIds.add(mainProjectSituation.getProjectId());
                    }
                    completeInvestment = BigDecimalUtil.add(completeInvestment, mainProjectSituation.getCompleteInvestment());
                    completeInvestment = BigDecimalUtil.add(completeInvestment, mainProjectSituation.getLastCompleteInvestment());
                }
                BigDecimal companyProportion = BigDecimalUtil.divide(completeInvestment, planInvestment, 2, BigDecimal.ROUND_HALF_UP, 100);
                companyProportionList.add(companyProportion != null ? companyProportion : 0);
            } else {
                companyProportionList.add(new BigDecimal(0));
            }
        });

        List<SeriesVO> seriesVOS = new ArrayList<>();
        seriesVOS.add(SeriesVO.builder().name("完成率").type("bar").data(companyProportionList).build());
        xAxisVOS.add(XAxisVO.builder().data(xList).build());
        ChartsVO chartsVO = ChartsVO.builder().legend(legendVO).ids(ids)
                .xAxis(xAxisVOS).series(seriesVOS).build();
        return chartsVO;
    }

//	@Override TODO DEL
//	public ChartsVO statisticsMainProject(BaseInvestmentExecutionNewDTO baseInvestmentExecutionDTO) {
//		/**
//		 * 填报年月为空时默认为当前月份
//		 */
//		String filingMonth = baseInvestmentExecutionDTO.getReportTime();
//		if (StringUtil.isBlank(filingMonth)){
//			filingMonth = DateUtil.format(DateUtil.now(), DateUtil.PATTERN_MONTH);
//		}
//
//		List<String> fillingUnitIds = new ArrayList<>();
//		boolean flag = false;
//		String orgId = baseInvestmentExecutionDTO.getOrgId();
//		if (Optional.ofNullable(orgId).isPresent()){
//			try {
//				PageData org = orgzationDao.findbyid(orgId);
//				if (!"0".equals(org.getString("parentId"))) {
//					fillingUnitIds.add(orgId);
//					flag = true;
//				}
//			}catch (Exception e){
//				log.error("statisticsMainProject---->获取单位失败");
//			}
//
//
//		}
//		List<MainProjectSummaryVO> results;
//		if(flag){
//			//单个企业 按项目类型
//			results = mainProjectSituationMapper.projectNatureSummaryByMonth(orgId, filingMonth, filingMonth.split(StringPool.DASH)[0]);
//		}else {
//			//国资委 按单位统计
//			results = mainProjectSituationMapper.summaryByMonth(fillingUnitIds, filingMonth, filingMonth.split(StringPool.DASH)[0]);
//		}
//
//		if (CollectionUtil.isEmpty(results)){
//			return null;
//		}
//
//		List<String> data = new ArrayList<>();
//		data.add("计划投资额");
//		data.add("实际投资额");
//		data.add("完成率");
//		LegendVO legendVO = LegendVO.builder().data(data).build();
//
//		List<XAxisVO> xAxisVOS = new ArrayList<>();
//		List<String> xList = new ArrayList<>();
//		List<Object> planTotalInvestmentList = new ArrayList<>();
//		List<Object> completeInvestmentList = new ArrayList<>();
//		List<Object> completeProportionList = new ArrayList<>();
//
//		BigDecimal endPlanTotalInvestment = new BigDecimal(0);
//		BigDecimal endCompleteInvestment = new BigDecimal(0);
//		for (MainProjectSummaryVO mainProjectSummaryVO : results){
//			if (StringUtil.isNotBlank(CheckName.getAbbreviationName(mainProjectSummaryVO.getUnitCheck()))){
//				xList.add(CheckName.getAbbreviationName(mainProjectSummaryVO.getUnitCheck()));
//			}else {
//				xList.add(mainProjectSummaryVO.getUnitCheck());
//			}
//			planTotalInvestmentList.add(mainProjectSummaryVO.getPlanTotalInvestment() != null ?
//					BigDecimalUtil.divide(mainProjectSummaryVO.getPlanTotalInvestment(), new BigDecimal(10000), 2, BigDecimal.ROUND_HALF_UP) : 0);
//			completeInvestmentList.add(mainProjectSummaryVO.getCompleteInvestment() != null ?
//					BigDecimalUtil.divide(mainProjectSummaryVO.getCompleteInvestment(), new BigDecimal(10000), 2, BigDecimal.ROUND_HALF_UP) : 0);
//			endPlanTotalInvestment = BigDecimalUtil.add(endPlanTotalInvestment, mainProjectSummaryVO.getPlanTotalInvestment());
//			endCompleteInvestment = BigDecimalUtil.add(endCompleteInvestment, mainProjectSummaryVO.getCompleteInvestment());
//			completeProportionList.add(BigDecimalUtil.divide(mainProjectSummaryVO.getCompleteInvestment(), mainProjectSummaryVO.getPlanTotalInvestment(),
//					2, BigDecimal.ROUND_HALF_UP,  100) + "%");
//		}
//
//		List<SeriesVO> seriesVOS = new ArrayList<>();
//		seriesVOS.add(SeriesVO.builder().name("计划投资额").type("bar").data(planTotalInvestmentList).build());
//		seriesVOS.add(SeriesVO.builder().name("实际投资额").type("bar").data(completeInvestmentList).build());
//		seriesVOS.add(SeriesVO.builder().name("完成率").type("bar").data(completeProportionList).build());
//		xAxisVOS.add(XAxisVO.builder().data(xList).build());
//
//		List<String> total = new ArrayList<>();
//		total.add("重点项目计划总投资: " + BigDecimalUtil.divide(endPlanTotalInvestment, new BigDecimal(10000), 2, BigDecimal.ROUND_HALF_UP) + "亿元");
//		total.add("累计实际投资额: " + BigDecimalUtil.divide(endCompleteInvestment, new BigDecimal(10000), 2, BigDecimal.ROUND_HALF_UP) + "亿元");
//		total.add("完成率: " + BigDecimalUtil.divide(endCompleteInvestment, endPlanTotalInvestment, 2, BigDecimal.ROUND_HALF_UP,  100) + "%");
//		ChartsVO chartsVO = ChartsVO.builder().legend(legendVO)
//				.xAxis(xAxisVOS).series(seriesVOS).total(total)
//				.build();
//		return chartsVO;
//	}

//	@Override TODO DEL
//	public BigDecimal completeProportion(boolean isGZW, String fillingMonth, String orgId) {
//		BaseInvestmentExecutionNewDTO baseInvestmentExecutionDTO = new BaseInvestmentExecutionNewDTO();
//		List<String> fillingUnitIds = new ArrayList<>();
//		if (!isGZW){
//			fillingUnitIds.add(orgId);
//		}
//		baseInvestmentExecutionDTO.setFilingMonth(fillingMonth);
//		baseInvestmentExecutionDTO.setFillingUnitIds(fillingUnitIds);
//		List<InvestmentMonthSummaryVO> results = effectiveInvestmentService.summary(baseInvestmentExecutionDTO);
//		BigDecimal endPlanInvestmentTotal = new BigDecimal(0);
//		BigDecimal endAllCompleteInvestmentList = new BigDecimal(0);
//		if (CollectionUtil.isNotEmpty(results)){
//			for (int i = 0; i < results.size()-1; i++){
//				InvestmentMonthSummaryVO result = results.get(i);
//				endPlanInvestmentTotal = BigDecimalUtil.add(endPlanInvestmentTotal, result.getPlanInvestmentTotal());
//				endAllCompleteInvestmentList = BigDecimalUtil.add(endAllCompleteInvestmentList, result.getAllCompleteInvestment());
//			}
//
//		}
//		BigDecimal endCompanyProportion = BigDecimalUtil.divide(endAllCompleteInvestmentList, endPlanInvestmentTotal, 2, BigDecimal.ROUND_HALF_UP, 100);
//		if(!Optional.ofNullable(endCompanyProportion).isPresent()){
//			endCompanyProportion = new BigDecimal(0);
//		}
//		return endCompanyProportion;
//	}

    @Override
    public EffectiveInvestmentVO statisticsProjectByCompany(BaseInvestmentExecutionNewDTO baseInvestmentExecutionDTO) {
        List<ExecutionProjectSituationVO> dataList = baseMapper.queryExecutionProjectByMonth(baseInvestmentExecutionDTO.getFillingUnitIds(), baseInvestmentExecutionDTO.getFillingMonth());
        if (CollectionUtil.isEmpty(dataList)) {
            return EffectiveInvestmentVO.builder().fixedProjectSituationVOS(new ArrayList<>()).stakeProjectSituationVOS(new ArrayList<>()).build();
        }

        EffectiveInvestmentVO result = new EffectiveInvestmentVO();
        Map<Integer, List<ExecutionProjectSituationVO>> dataMap = dataList.stream().collect(Collectors.groupingBy(ExecutionProjectSituationVO::getProjectType));
        List<ExecutionProjectSituationVO> fixedProjectSituationVOS = new ArrayList<>();
        List<ExecutionProjectSituationVO> stakeProjectSituationVOS = new ArrayList<>();
        if (dataMap.containsKey(1)) {
            stakeProjectSituationVOS.addAll(dataMap.get(1));
            stakeProjectSituationVOS.add(subTotal(dataMap.get(1)));
        }

        if (dataMap.containsKey(2)) {
            fixedProjectSituationVOS.addAll(dataMap.get(2));
            fixedProjectSituationVOS.add(subTotal(dataMap.get(2)));
        }
        result.setFixedProjectSituationVOS(fixedProjectSituationVOS);
        result.setStakeProjectSituationVOS(stakeProjectSituationVOS);
        return result;
    }

    @Override
    public List<ExecutionProjectSituationVO> statisticsProjectByProjectNature(BaseInvestmentExecutionNewDTO baseInvestmentExecutionDTO) {
        List<ExecutionProjectSituationVO> dataList = baseMapper
                .queryExecutionProjectByMonthNoProjectNatureName(baseInvestmentExecutionDTO.getFillingUnitIds(), baseInvestmentExecutionDTO.getFillingMonth());

        List<ExecutionProjectSituationVO> initList = init();
        if (CollectionUtil.isEmpty(dataList)) {
            return initList;
        }
        Map<String, List<ExecutionProjectSituationVO>> dataMap = dataList.stream().collect(Collectors.groupingBy(ExecutionProjectSituationVO::getProjectNatureId));
        List<ExecutionProjectSituationVO> results = new ArrayList<>();
        for (ExecutionProjectSituationVO initVO : initList) {
            if (dataMap.containsKey(initVO.getProjectNatureId())) {
                List<ExecutionProjectSituationVO> voList = dataMap.get(initVO.getProjectNatureId());
                voList.get(0).setProjectNatureName(initVO.getProjectNatureName());
                results.addAll(voList);
                ExecutionProjectSituationVO subTotal = subTotal(voList);
                subTotal.setProjectNatureName(subTotal.getFillingUnitName());
                subTotal.setFillingUnitName(null);
                results.add(subTotal);
            }
        }
        return results;
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public String saveProjectExecution(String data) {
        YthResult ythResult = new YthResult();
        //成功的id集合
        List<String> successIds = new ArrayList<>();
        //失败的id集合
        List<String> failIds = new ArrayList<>();
        //失败的原因
        List<String> failReasons = new ArrayList<>();
        //将json字符串转换成list
        List<BaseInvestmentExecutionNew> dataList = JSON.parseArray(data, BaseInvestmentExecutionNew.class);
        if (CollectionUtil.isNotEmpty(dataList)) {
            Map<String, String> orgSourceMap = orgService.getSourceId();
            //根据datasourceIds 查询出所有的数据
            List<BaseInvestmentExecutionNew> list = list(new LambdaQueryWrapper<BaseInvestmentExecutionNew>().in(BaseInvestmentExecutionNew::getDataSourceId, dataList.stream().map(BaseInvestmentExecutionNew::getDataSourceId).toArray()));
            if (CollectionUtil.isNotEmpty(list)) {
                //删除子集
                List<Long> ids = list.stream().map(BaseInvestmentExecutionNew::getId).collect(Collectors.toList());
                effectiveInvestmentService.remove(new LambdaQueryWrapper<EffectiveInvestment>().in(EffectiveInvestment::getBaseInvestmentExecutionId, ids));
                fundProjectService.remove(new LambdaQueryWrapper<FundProject>().in(FundProject::getBaseInvestmentExecutionId, ids));
            }
            //如果数据库中有数据，就更新，没有就新增
            for (BaseInvestmentExecutionNew entity : dataList) {
                transfer(entity, orgSourceMap);
                //id重复略过
                if (CollectionUtil.isNotEmpty(list)) {
                    List<String> olIds = list.stream().map(BaseInvestmentExecutionNew::getDataSourceId).collect(Collectors.toList());
                    String dataSourceId = entity.getDataSourceId();
                    //判断数据库中是否有数据
                    if (olIds.contains(dataSourceId)) {
                        for (BaseInvestmentExecutionNew oldEntity : list) {
                            if (dataSourceId.equals(oldEntity.getDataSourceId())) {
                                //判断status是否为0，如果是0，就更新，不是0，就不更新
                                if (CheckStatus.checkCode(oldEntity.getStatus())) {
                                    successIds.add(dataSourceId);
                                    entity.setId(oldEntity.getId());
                                    entity.setDataSource(YthConstant.DATA_NINGBO);
                                    submit(entity);
                                    list.remove(oldEntity);
                                    break;
                                } else {
                                    failIds.add(dataSourceId);
                                    failReasons.add("dataSourceId:" + dataSourceId + "数据已提交且已经在流程中，无法更新");
                                    break;
                                }
                            }
                        }
                    } else {
                        //如果数据库中没有数据，就新增
                        entity.setDataSource(YthConstant.DATA_NINGBO);
                        submit(entity);
                        successIds.add(entity.getDataSourceId());
                    }
                } else {
                    //如果数据库中没有数据，就新增
                    entity.setDataSource(YthConstant.DATA_NINGBO);
                    submit(entity);
                    successIds.add(entity.getDataSourceId());
                }
            }
        } else {
            failReasons.add("数据为空");
        }
        ythResult.setSuccessIds(successIds);
        ythResult.setFailIds(failIds);
        ythResult.setFailReason(StringUtils.join(failReasons, ";"));
        //ythResult转换成json字符串
        return JSON.toJSONString(ythResult);
    }

    private void transfer(BaseInvestmentExecutionNew entity, Map<String, String> orgSourceMap) {
        Optional.ofNullable(entity.getFilingUnitId()).ifPresent(m ->
                {
                    String orgId = orgSourceMap.get(m);
                    if (StringUtil.isNotBlank(orgId)) {
                        entity.setFilingUnitId(orgId);
                        entity.setCreateCompanyId(orgId);
                    }
                }
        );

    }

    private List<ExecutionProjectSituationVO> init() {
        Map<String, String> map = baseInfoService.getChildMap(ValueSetConstant.PROJECT_NATURE);
        List<ExecutionProjectSituationVO> initList = new ArrayList<>();
        map.forEach((k, v) -> {
            if (!v.contains("(旧)")) {
                ExecutionProjectSituationVO situationVO = new ExecutionProjectSituationVO();
                situationVO.setProjectNatureId(k);
                situationVO.setProjectNatureName(v);
                initList.add(situationVO);
            }
        });
        initList.sort(Comparator.comparing(o -> Integer.valueOf(o.getProjectNatureId())));

        return initList;
    }

    private ExecutionProjectSituationVO subTotal(List<ExecutionProjectSituationVO> dataList) {
        ExecutionProjectSituationVO subTotal = new ExecutionProjectSituationVO();
        subTotal.setFillingUnitName("累计");
        subTotal.setProjectName(String.valueOf(dataList.size()));
        for (ExecutionProjectSituationVO situationVO : dataList) {
            subTotal.setPlanTotalInvestment(BigDecimalUtil.add(subTotal.getPlanTotalInvestment(), situationVO.getPlanTotalInvestment()));
            subTotal.setLastCompleteInvestment(BigDecimalUtil.add(subTotal.getLastCompleteInvestment(), situationVO.getLastCompleteInvestment()));
            subTotal.setCompleteInvestment(BigDecimalUtil.add(subTotal.getCompleteInvestment(), situationVO.getCompleteInvestment()));
        }
        return subTotal;
    }

    private static Map<String, String> fileNameMap = new HashMap<>();

    @Override
    public String export(String filingYear) {
        String key = System.currentTimeMillis() + StringPool.DASH + UUID.randomUUID().toString().replace(StringPool.DASH, "");
        String fileName = key + ".xlsx";
        String exportPath = environment.getProperty("excel.path");
        /**
         * 导出路径不存在则创建
         */
        File file = new File(exportPath);
        if (!file.exists()) {
            file.mkdirs();
        }
        InputStream inputStream = this.getClass().getResourceAsStream("/exceldemo/baseInvestmentExecutionNewExport.xlsx");
        ExcelWriter excelWriter = EasyExcel.write(exportPath + fileName).withTemplate(inputStream).build();
        FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();

        // 获取数据
        Query query = new Query();
        query.setFlag(1);
        QueryWrapper<BaseInvestmentExecutionNew> queryWrapper = SearchParamEntiy.getQueryWrapper(
                Condition.getQueryWrapper(new BaseInvestmentExecutionNew()), query.getSearch()
        );
        TokenSearch<BaseInvestmentExecutionNew> tokenSearch = new TokenSearch<>();

        tokenSearch.addTokenQuery(queryWrapper, query);
        queryWrapper.eq(StringUtils.isNotBlank(filingYear), "filing_year", filingYear);
        queryWrapper.orderByDesc("filing_month");

        List<BaseInvestmentExecutionNewVO> voList = baseInvestmentExecutionWrapper.entityToVO(this.list(queryWrapper));
        List<BaseInvestmentExecutionNewExport> exportList = BeanUtil.copyToList(voList, BaseInvestmentExecutionNewExport.class);

        List<Long> projectIds = voList.stream().map(BaseInvestmentExecutionNewVO::getImProjectId).collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(projectIds)) {
            List<ProjectInfo> projectList = projectInfoMapper.selectList(new LambdaQueryWrapper<ProjectInfo>().in(ProjectInfo::getId, projectIds));

            // 获取省编码map
            Map<String, String> provinceMap = new HashMap<>();
            Set<String> provinceCodes = projectList.stream().map(ProjectInfo::getProvinceCode).collect(Collectors.toSet());
            if (CollectionUtil.isNotEmpty(provinceCodes)) {
                List<Region> list = regionService.list(new LambdaQueryWrapper<Region>().in(Region::getCode, provinceCodes));
                provinceMap = list.stream().collect(Collectors.toMap(Region::getCode, Region::getName, (a, b) -> b));
            }
            // 市编码map
            Map<String, String> cityMap = new HashMap<>();
            Set<String> cityCodes = projectList.stream().map(ProjectInfo::getCityCode).collect(Collectors.toSet());
            if (CollectionUtil.isNotEmpty(cityCodes)) {
                List<Region> list = regionService.list(new LambdaQueryWrapper<Region>().in(Region::getCode, cityCodes));
                cityMap = list.stream().collect(Collectors.toMap(Region::getCode, Region::getName, (a, b) -> b));
            }
            // 县编码map
            Map<String, String> areaMap = new HashMap<>();
            Set<String> areaCodes = projectList.stream().map(ProjectInfo::getAreaCode).collect(Collectors.toSet());
            if (CollectionUtil.isNotEmpty(areaCodes)) {
                List<Region> list = regionService.list(new LambdaQueryWrapper<Region>().in(Region::getCode, areaCodes));
                areaMap = list.stream().collect(Collectors.toMap(Region::getCode, Region::getName, (a, b) -> b));
            }

            List<ProjectInfoVO> projectInfoVOS = projectInfoWrapper.entityToVO(projectList);
            Map<Long, ProjectInfoVO> projectMap = projectInfoVOS.stream().collect(Collectors.toMap(ProjectInfoVO::getId, a -> a));
            String[] ignores = {"id", "createUser", "createDept", "createTime", "updateUser", "updateTime", "status",
                    "isDeleted", "createCompanyId"};
            for (BaseInvestmentExecutionNewExport a : exportList) {
                if (projectMap.containsKey(a.getImProjectId())) {
                    ProjectInfoVO projectInfo = projectMap.get(a.getImProjectId());
                    BeanUtil.copyProperties(projectInfo, a, ignores);
                }
                a.setProvinceCodeName(provinceMap.get(a.getProvinceCode()));
                a.setCityCodeName(cityMap.get(a.getCityCode()));
                a.setAreaCodeName(areaMap.get(a.getAreaCode()));
            }
        }

        List<BaseInvestmentExecutionNewExport> firstList = exportList.stream()
                .filter(a -> a.getInvestmentCategory() == 2).collect(Collectors.toList());

        List<BaseInvestmentExecutionNewExport> secondList = exportList.stream()
                .filter(a -> a.getInvestmentCategory() == 1).collect(Collectors.toList());

        // 写sheet页
        WriteSheet investWriteSheet = EasyExcel.writerSheet(0).build();

        // 其他参数可以使用Map封装
        Map<String, Object> otherMap = new HashMap<>(16);
        otherMap.put("fillYear", filingYear);
        BaseInvestmentExecutionNewExport export = CollectionUtil.isEmpty(exportList)? null : exportList.get(0);
        otherMap.put("company", null != export ? export.getSubordinateGroupName() : "");
        Date now = DateUtil.now();
        otherMap.put("year", DateUtil.format(now, "yyyy"));
        otherMap.put("month", DateUtil.format(now, "MM"));
        otherMap.put("day", DateUtil.format(now, "dd"));
        excelWriter.fill(otherMap, investWriteSheet);


        WriteSheet investWriteSheetTwo = EasyExcel.writerSheet(1).build();
        excelWriter.fill(firstList, fillConfig, investWriteSheetTwo);
        excelWriter.fill(otherMap, investWriteSheetTwo);

        WriteSheet investWriteSheetThree = EasyExcel.writerSheet(2).build();
        excelWriter.fill(secondList, fillConfig, investWriteSheetThree);
        excelWriter.fill(otherMap, investWriteSheetThree);


        excelWriter.finish();
        PageData org = orgzationService.getCompanyNameById(TokenUtil.getTokenOrgId());
        String companyName = "";
        if (org != null) {
            companyName = org.getString("name");
        }

        String excelName = companyName + "_项目投资计划执行情况";
        fileNameMap.put(key, excelName);
        return key;
    }

    @Override
    public void download(String key, HttpServletResponse response) {
        if (!fileNameMap.containsKey(key)) {
            log.error("BaseInvestmentPlanServiceImpl 导出excel失败--------> key " + key);
            return;
        }
        String excelName = fileNameMap.get(key);
        String excelPath = environment.getProperty("excel.path") + "/" + key + ".xlsx";
        FileTools.exportExcel(excelPath, excelName, response);
        fileNameMap.remove(key);
    }
}
